<?php
	defined('BASEPATH') OR exit('No direct script access allowed');
/**
 * 模型基类
 * @property CI_DB_query_builder $db
 */
class MY_Model extends CI_Model{
	protected $_table='';
	protected $_pk = 'id';
	/**
	 * 用户表
	 */
	const T_USER  = 'hs_user';
	/**
	 * 用户登录记录表
	 */
	const T_USER_LOGIN_LOG = 'hs_user_login_log';
	
	/**
	 * 赠送纪录表
	 */
	const T_PRESRENT = 'hs_presrent';
	/**
	 * 测试人员信息表
	 */
	const T_TESTER = 'hs_tester';
	/**
	 * 买水订单表(14天之内)
	 */
	const T_ORDER = 'hs_order';
	/**
	 * 旧买水订单表(14天之前)
	 */
	const T_ORDER_OLD = 'hs_order_old';
	
	/**
	 * 买水订单视图
	 */
	const V_ORDER = 'hs_order_view';
	/**
	 * 设备表
	 */
	const T_DEV   = 'hs_dev';
	/**
	 * 用户设备表
	 */
	const T_USER_DEV = 'hs_user_dev';
	/**
	 * 充值订单表
	 */
	const T_RECHARGE_ORDER = 'hs_recharge_order';
	/**
	 * APP版本表
	 */
	const T_APP_VERSION    = 'hs_app_version';
	/**
	 * 学校表
	 */
	const T_SCHOOL = 'hs_school';
	/**
	 * 用户友盟信息表
	 */
	const T_USER_UM_INFO  = 'hs_user_um_info' ;
	
	/**
	 * 友盟推送消息记录表
	 */
	const T_UM_LOG = 'hs_um_log';
	
	
	const T_M_ADMIN      = 'hs_mng_admin';
	const T_M_ROLE       = 'hs_mng_role';
	const T_M_MENU       = 'hs_mng_menu';
	const T_M_ADMIN_ROLE = 'hs_mng_admin_role';
	const T_M_ROLE_MENU  = 'hs_mng_role_menu';
	const V_M_ADMIN_MENU = 'hs_mng_admin_menu_view';
	

	public function __construct(){
		parent::__construct();
		$this->load->database('default');
	}
	/**
	 * 获取表名
	 */
	protected  function _table (){
	    return $this->_table;
	}

	public function getList($select='*',$where='',$limit='',$offset='',$order='',$sort='',$group=''){
		if( is_array($select) ){
			return $this->_getList($select);
		}
		empty($select) && $select='*';
		if( $where ){
			$this->db->where($where);
		}

		if( $limit ){
			$this->db->limit((int)$limit);
			if( $offset ){
				$this->db->offset((int)$offset);
			}
		}

		if( $order ){
			empty($sort) && $sort='DESC';
			$this->db->order_by($order,$sort);
		}

		return $this->db->select($select)->from($this->_table())->get()->result_array();

	}
	public function getListHaveWhereIn($select='*',$where='',$where_in='',$limit='',$offset='',$order='',$sort='',$group=''){
		if( is_array($select) ){
			return $this->_getList($select);
		}
		empty($select) && $select='*';
		if( $where ){
			$this->db->where($where);
		}
		if( $where_in ){ 
			$this->db->where_in('id',$where_in);
		}

		if( $limit ){
			$this->db->limit((int)$limit);
			if( $offset ){
				$this->db->offset((int)$offset);
			}
		}

		if( $order ){
			empty($sort) && $sort='DESC';
			$this->db->order_by($order,$sort);
		}

		return $this->db->select($select)->from($this->_table())->get()->result_array();

	}
	protected function _getList($query){
	    $select = '*';
	    foreach ($query as $k => $v){
	        if( empty($v) ){
	            continue;
	        }
	        switch ($k) {
	            case 'select':
	               $select = (string)$v;
	               break;
	            case 'where':
	                $this->db->where($v);
	                break;
	            case 'like':
	                $this->db->like($v);
	                break;
	            case 'where_in':
	                $_field = isset($v['field']) ? $v['feild'] : (isset($v[0]) ? $v[0] : '');
	                $_list  = isset($v['list']) ? $v['list'] : (isset($v[1]) ? $v[1] : '');
	                if( $_field && $_list ){
	                    $this->db->where_in( (string)$_field,(array)$_list );
	                }
	                break;
	            case 'order':
	                $sort = 'ASC';
	                if ( isset($query['sort']) ) {
	                    $sort = strtoupper($query['sort']);
	                    $sort = $sort === 'DESC' ? 'DESC' : 'ASC';
	                    unset($query['sort']);
	                }
	                $this->db->order_by($v,$sort);
	                break;
	            case 'limit':
	                $this->db->limit( abs( (int)$v ) );
	                break;
                case 'offset':
                    $this->db->offset( abs( (int)$v ) );
                    break;
                case 'group':
                    $this->db->group_by($v);
                    break;
                case 'join':
                    $joins = array();
                    $joinSelect = '';
                    if( isset($v['table']) ){
                        $joins[] = $v;
                    }else{
                        $joins = $v;
                    }
                    foreach ($joins as $join){
                        if ( !isset($join['table']) && !isset($join['on']) ) {
                            continue;
                        }
                        $_type = isset($join['type']) ? $join['type'] : '';
                        if ( isset($join['select']) ){
                            $_select = str_replace(',', ','.$join['table'].'.', $join['select']);
                            $joinSelect .= $join['table'].'.'.$_select;
                        }
                        $this->db->join($join['table'],$join['on'],$_type);
                    }
                    break;
	        }// END switch
	    }// END foreach
	    if( !empty($joinSelect) ){
	        $select = str_replace(',', ','.$this->_table().'.', $select);
	        $select.= ','.$joinSelect;
	    }
	    return $this->db->select($select)->from($this->_table())->get()->result_array();
	}

	public function getOne($where,$select='*'){
		return $this->db->select($select)
					->where($where)
					->from($this->_table())
					->limit(1)
					->get()
					->row_array();
	}
	
	public function getColList($field='id',$where='',$like=''){
		$select = $field;
		$list = $this->db->where($where)
						->like($like)
						->from( $this->_table() )
						->get()
						->reuslt_array();
		return array_column($list, $field);
	}
	/**
	 * 通过字段的值列表获取列表
	 * @param string $select
	 * @param string $field
	 * @param array $values
	 * @return array
	 */
	public function getListByFieldList($select,$field,$values){
		$values = array_unique($values);
		$list = $this->db->select($select)->where_in($field,$values)->get($this->_table())->result_array();
		if( empty($list) ){
			return array();
		}
		return array_combine( array_column($list, $field) , $list);
	}
	/**
	 * 通过一列的的值获取列表
	 * @param string $select
	 * @param string $colName 列名
	 * @param array $values 列的值列表
	 */
	public function getListByColValues($select,$colName,$values){
		return $this->db->select($select)
						->where_in($colName,array_unique($values))
						->get($this->_table())
						->result_array();
	}
	

	public function getOneById($id,$select='*'){
		return $this->db->select($select)
			            ->from($this->_table())
			            ->where($this->_pk,$id)
			            ->get()
			            ->row_array();
	}

	public function insert($data){
		if($this->db->insert($this->_table(),$data)){
			return $this->db->insert_id();
		}

		return false;

	}
	
	public function insertBatch($data){
		return $this->db->insert_batch($this->_table(),$data);
	}

	public function update($where,$data){
		return $this->db->where($where)->update($this->_table(),$data) ;
	}
	public function updateOne($key='id',$val,$data){
		$where = array($key=>$val);
		return $this->update($where, $data);
	}
	
	public function increment($where,$key,$step=1){
		return $this->db->set($key,"{$key}+1",FALSE)->where($where)->update($this->_table());
	}

	public function delete($where){
		return $this->db->where($where)->delete($this->_table());
	}
	
	public function count($where='',$like=''){
		if ($where) {
			$this->db->where($where);
		}
		if ($like) {
			$this->db->like($like);
		}
		return (int)$this->db->select('count(*) as total')->from($this->_table())->get()->row()->total;
	}
	
	public function max($field,$where='',$like=''){
		if ($where) {
			$this->db->where($where);
		}
		if ($like) {
			$this->db->like($like);
		}
		return (int)$this->db->select('MAX('.$field.') AS max')->from($this->_table())->get()->row()->max;
	}
	
	public function replace($data){
		return $this->db->replace($this->_table(),$data);
	}
}

/**
 * mongo模型基类
 * @property Mongo_db $mongo mongo连接类
 */
class Mongo_Model extends CI_Model{
	/**
	 * 要使用的db名称
	 * 
	 * @var string
	 */
	protected $dbName = 'hs';
	/**
	 * mongo集合名称
	 * 
	 * @var string
	 */
	protected $collName = NULL;
	/**
	 * mongo实例
	 * @var MongoClient
	 */
	protected $mongo = NULL;
	/**
	 * mongo集合对象
	 * 
	 * @var MongoCollection
	 */
	protected $coll = NULL;
	
	
	public function __construct() {
		$cfg = $this->getConfig();
		$this->mongo = new MongoClient("{$cfg['host']}:{$cfg['port']}");
		
		if( $this->dbName && $this->collName ){
			$this->coll = $this->mongo->selectCollection($this->dbName,$this->collName) ;
		}
	}
	
	public function __destruct(){
		// 关闭mongo链接
		$this->close();
	}
	
	protected function getConfig(){
		return array(
				'host'=>'localhost',
				'port'=>'27017',
		);
	}
	
	
	public function find($where = array(),$fields=array()) {
		$list = $this->coll->find ( $where ,$fields);
		return $this->toArray($list);
	}
	protected function toArray($list){
		return empty ( $list ) ? array () : iterator_to_array ( $list ) ;
// 		return empty ( $list ) ? array () : array_values( iterator_to_array ( $list ) );
	}
	public function findOne($where = array()) {
		return $this->coll->findOne ( $where );
	}
	public function findOneByID($id) {
		$where = array ();
		$where ['_id'] = $id;
		return $this->coll->findOne ( $where );
	}
	public function remove($where, $options = NULL) {
		return $this->coll->remove ( $where, $options );
	}
	public function removeOneByID($id) {
		$where = array ();
		$options = array ();
		$where ['_id'] = $id;
		$options ['justOne'] = TRUE;
		return $this->coll->remove ( $where, $options );
	}
	public function insert($data, $options = array()) {
		try {
			$res = $this->coll->insert ( $data ,$options );
			return $res['ok']==1 ? TRUE : FALSE;
		} catch (Exception $e) {
			return FALSE;
		}
	}
	public function update($where, $update, $options = array()) {
		return $this->coll->update ( $where, $update, $options );
	}

	
	public function save($data,$options=array()){
		$res = $this->coll->save($data,$options);
		return array_key_exists('ok', $res) && $res['ok']==1;
	}
	
	public function count($where=array()){
		return $this->coll->count($where);
	}
	
	public function max($field,$where){
		$res=$this->coll->find($where,array($field))->sort(array($field=>-1))->limit(1)->getNext();
		return empty($res[$field]) ? 0 : $res[$field] ;
	}
	public function min($field,$where){
		$res=$this->coll->find($where,array($field))->sort(array($field=>1))->limit(1)->getNext();
		return empty($res[$field]) ? 0 : $res[$field] ;
	}
	
	public function close(){
		if (! empty ( $this->mongo )) {
			try {
				$this->mongo->close(TRUE);
			} catch (\Exception $e) {
				//\handleException($e,'mongo model close');
			}
		}
		$this->mongo = NULL;
		$this->coll = NULL;
	}
	
}























